<!--
 * @Author: your name
 * @Date: 2021-06-10 17:17:13
 * @LastEditTime: 2021-06-10 17:18:57
 * @LastEditors: Please set LastEditors
 * @Description: 课表管理
 * @FilePath: \hmid:\个人工具网站\ClassManage\src\views\Teach\timeTable.vue
-->
<template>
	<div class="editor">
		<div class="editor-left">
			<div class="work-iconfont icon-jiantou_youshang_o editor-left-shape" @click="addArrows"></div>
			<div 
			  v-for="(v,index) in shapeList"
			  :key="index"
			  draggable 
			  :class="['work-iconfont', v.class, 'editor-left-shape']"
			  @dragend="shapeMoveEnd($event,v)"></div>
		</div>
		<div class="editor-main">
			<div class="editor-fun">
				<span @click="saveInfo" class="work-iconfont icon-baocun1" title="保存"></span>
				<span @click="cleanInfo" class="work-iconfont icon-qingchu" title="清除"></span>
				<span @click="deleteNode" class="work-iconfont icon-shanchu" title="删除"></span>
			</div>
			<div class="editor-page" id="editorG6"></div>
		</div>
		<div class="editor-right">
			<div class="editor-right-form">
				<div class="editor-right-form-title">节点信息</div>
				<el-form label-position="left" label-width="60px" :model="formNode">
					<el-form-item label="ID:">
					  <el-input v-model="formNode.id" :disabled="true"></el-input>
					</el-form-item>
				  <el-form-item label="名称:">
				    <el-input v-model="formNode.label" @change="changeNodeLable"></el-input>
				  </el-form-item>
				</el-form>
			</div>
		</div>
	</div>
</template>

<script>
import G6 from '@antv/g6';
import Grid from '@antv/g6-plugin/lib/grid'
import Menu from '@antv/g6-plugin/lib/menu'
import { v4 as uuidv4 } from 'uuid'; // 生成唯一ID
export default {
	data() {
		return {
			shapeList: [
				{
					type: 'ellipse',
					labelInfo: 'node',
					size: [80, 40],
					class: 'icon-tuoyuanxing'
				},
				{
					type: 'rect',
					labelInfo: 'node',
					size: [80, 40],
					class: 'icon-fangxingweixuanzhong'
				},
				{
					type: 'circle',
					labelInfo: 'node',
					size: [50, 50],
					class: 'icon-yuanxingweixuanzhong'
				},
				{
					type: 'diamond',
					labelInfo: 'node',
					size: [80, 40],
					class: 'icon-tubiao'
				}
			],
			graph: null,
			nodeInfo: null,
			formNode: {}
		}
	},
	mounted() {
		this.$nextTick(() => {
			this.init()
		})
		// behover
		this.clickCanvas() // 点击画布
		this.hoverNode() // 点击node
		this.addEdge()   // 增加线条
		this.clickEdge() // 点击线条
		this.getUId()
	},
	methods:{
		getUId() {
			return uuidv4().split('-')[0];  // ⇨ '9b1deb4d'
		},
		init() {
			var _self = this
			const menu = new Menu({
				itemTypes: ['node'],
				getContent(e, graph) {
				    const outDiv = document.createElement('div');
				    outDiv.style.width = '60px';
				    outDiv.innerHTML = `<div custom-param="delete" class="editor-menu-item">删除</div>`
				    return outDiv
				},
				handleMenuClick(target, item, graph) {
					return _self.nodeMenuClick(target, item, graph)
				},
			})
			const grid = new Grid()
			this.graph = new G6.Graph({
			  container: 'editorG6',
			  
			  modes: {
			      default: ['click-canvas', 'hover-node', 'drag-node', 'click-edge'],
				  addEdge: ['click-add-edge'],
			  },
			  plugins: [grid, menu],
			})
			if(localStorage.getItem('nodeInfo')) {
				let data = JSON.parse(localStorage.getItem('nodeInfo'))
				this.graph.read(data)
			}
		},
		shapeMoveEnd(e, item) {
			const xy = this.graph.getPointByClient(e.x, e.y)
			const model = {
			  id: this.getUId(),
			  label: item.labelInfo,
			  shape: item.type,
			  type: item.type,
			  size: item.size,
			  x: xy.x,
			  y: xy.y,
			  style: {
			  	fill: 'white'
			  }
			}
			this.graph.addItem('node', model)
		},
		// 点击画布
		clickCanvas() {
			var _self = this
			G6.registerBehavior('click-canvas', {
				getEvents() {
					return {
						'canvas:click': 'onCanvasClick'
					}
				},
				onCanvasClick(ev) {
					console.log('点击画布', ev)
					// 点击画布时清空选中的节点信息
					_self.nodeInfo = {}
					_self.formNode = {}
				}
			})
		},
		// 点击线条
		clickEdge() {
			var _self = this
			G6.registerBehavior('click-edge', {
				getEvents() {
					return {
						'edge:click': 'onEdgeClick'
					}
				},
				onEdgeClick(ev) {
					const node = ev.item
					_self.nodeInfo = node.getModel()
					_self.formNode = {}
				}
			})
		},
		// 移入node节点
		hoverNode() {
			var _self = this
			G6.registerBehavior('hover-node', {
				// 设定该自定义行为需要监听的事件及其响应函数
				getEvents() {
				    return {
						'node:mousedown': 'onMousedown'
				    }
				},
				// 鼠标在node按下触发
				onMousedown(ev) {
					const node = ev.item
					_self.nodeInfo = node.getModel()
					_self.formNode = node.getModel()
					this.graph.setMode('default')
				},
			})
		},
		addArrows() {
			this.graph.setMode('addEdge')
		},
		// 增加箭头
		addEdge() {
			G6.registerBehavior('click-add-edge', {
				// 设定该自定义行为需要监听的事件及其响应函数
				 getEvents() {
				    return {
						'node:click': 'onClick', // 监听事件 node:click，响应函数时 onClick
						mousemove: 'onMousemove', // 监听事件 mousemove，响应函数时 onMousemove
						'edge:click': 'onEdgeClick', // 监听事件 edge:click，响应函数时 onEdgeClick
				    };
				},
				// getEvents 中定义的 'node:click' 的响应函数
				onClick(ev) {
				    const node = ev.item;
				    const graph = this.graph;
				    // 鼠标当前点击的节点的位置
				    const point = { x: ev.x, y: ev.y };
				    const model = node.getModel();
				    if (this.addingEdge && this.edge) {
				      graph.updateItem(this.edge, {
				        target: model.id,
				      });
				      this.edge = null;
				      this.addingEdge = false;
					  this.graph.setMode('default')
				    } else {
				      // 在图上新增一条边，结束点是鼠标当前点击的节点的位置
				      this.edge = graph.addItem('edge', {
				        source: model.id,
				        target: point,
						style: {
						  endArrow: true
						},
						color: '#000'
				      });
				      this.addingEdge = true;
				    }
				},
				// getEvents 中定义的 mousemove 的响应函数
				onMousemove(ev) {
				    // 鼠标的当前位置
				    const point = { x: ev.x, y: ev.y };
				    if (this.addingEdge && this.edge) {
				      // 更新边的结束点位置为当前鼠标位置
				      this.graph.updateItem(this.edge, {
				        target: point,
				      });
				    }
				},
				// getEvents 中定义的 'edge:click' 的响应函数
				onEdgeClick(ev) {
				    const currentEdge = ev.item;
				    // 拖拽过程中，点击会点击到新增的边上
				    if (this.addingEdge && this.edge == currentEdge) {
				      this.graph.removeItem(this.edge);
				      this.edge = null;
				      this.addingEdge = false;
					  this.graph.setMode('default')
				    }
				},
			});
		},
		// 保存信息
		saveInfo() {
			console.log('保存信息: ', this.graph.save())
			// localStorage.setItem('nodeInfo', JSON.stringify(this.graph.save()))
		},
		// 清除信息
		cleanInfo() {
			// 清除画布上的属性内容
			localStorage.clear()
			this.graph.clear()
		},
		// 删除节点
		deleteNode() {
			if(Object.keys(this.nodeInfo).length !== 0) {
				this.graph.remove(this.nodeInfo.id)
				if(this.nodeInfo.id === this.formNode.id) {
					this.formNode = {}
				}
			}else {
				this.$message({
				  message: '未选择删除内容',
				  type: 'warning'
				});
			}
		},
		// 右键node菜单选择
		nodeMenuClick(target, item, graph) {
			const node = item.getModel()
			if(target.getAttribute('custom-param') == 'delete') {
				graph.remove(node.id)
			}
		},
		changeNodeLable() {
			const item = this.graph.findById(this.nodeInfo.id)
			this.graph.updateItem(item, this.formNode)
		}
	}
}
</script>

<style lang="scss">
@import './iconfont/iconfont.css';
.editor {
	height: 100%;
	width: 100%;
	display: flex;
	.editor-main {
		height: 100%;
		flex: 1;
		.editor-fun {
			height: 40px;
			line-height: 40px;
			span {
				font-size: 22px;
				margin-right: 20px;
				&:hover {
					color: #409EFF;
				}
			}
		}
		.editor-page {
			border: 1px solid #000000;
			box-sizing: border-box;
			height: 500px;
			.editor-menu-item {
				cursor: pointer;
				&:hover {
					color: #409EFF;
				}
			}
		}
	}
	.editor-left {
		width: 80px;
		height: 100px;
		.editor-left-shape {
			margin: 10px 0;
			text-align: center;
			font-size: 40px;
			cursor: pointer;
			&:hover {
				color: #ff6700;
			}
		}
	}
	.editor-right {
		width: 200px;
		.editor-right-form {
			padding: 10px;
			.editor-right-form-title {
				margin-bottom: 8px;
			}
		}
	}
}
</style>